package org.gavin.sharding.controller;

import com.mybatisflex.annotation.UseDataSource;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.database.annotation.NeedDecrypt;
import org.database.annotation.NeedEncrypt;
import org.gavin.core.annotation.LogRecord;
import org.gavin.core.domain.R;
import org.gavin.sharding.entity.TUser;
import org.gavin.sharding.entity.TbAccount;
import org.gavin.sharding.service.TUserService;
import org.gavin.sharding.service.TbAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static org.gavin.sharding.entity.table.TUserTableDef.T_USER;

/**
 * UserController
 *
 * @author grl
 * @date 2024/1/31
 */
@Slf4j
@RestController
public class UserController {

    @Autowired
    private TUserService userService;
    @Autowired
    private TbAccountService accountService;

    @PostMapping(value = "/add/user")
    @UseDataSource(value = "sharding-db")
    @Transactional(rollbackFor = Exception.class)
    public R<Page<TUser>> addUser(@RequestBody TUser user){
        LocalDateTime now = LocalDateTime.now();
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(T_USER.CREATE_TIME.ge(LocalDateTime.now().minusMonths(1)));
        Page<TUser> page = userService.page(Page.of(1, 2), queryWrapper);
        user.setCreateTime(now);
        user.setUpdateTime(now);
        userService.save(user);
        return R.ok(page);
    }

    @PostMapping(value = "/page/user/list")
    @UseDataSource(value = "sharding-db")
    public R<Page<TUser>> getUserPageList(){
        QueryWrapper queryWrapper = new QueryWrapper();
        //queryWrapper.where(T_USER.CREATE_TIME.ge(LocalDateTime.now().minusMonths(1)));
        Page<TUser> page = userService.page(Page.of(1, 2), queryWrapper);
        return R.ok(page);
    }

    @PostMapping(value = "/user/list")
    @UseDataSource(value = "sharding-db")
    public R<List<TUser>> getUser(){
        List<TUser> tUsers = userService.getMapper().selectAll();
        return R.ok(tUsers);
    }

    @GetMapping(value = "/user/age")
    public R<TUser> getUserAge(@RequestParam(value = "age") Integer age){
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(T_USER.AGE.eq(age));
        TUser objAs = userService.getOne(queryWrapper);
        return R.ok(objAs);
    }

    public R<TUser> getUserId(){
        DataSourceKey.use("sharding-db");
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(T_USER.CREATE_TIME.eq(LocalDateTime.parse("20240204 15:18:30", DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss"))));
        TUser objAs = userService.getOne(queryWrapper);
        return R.ok(objAs);
    }

    @LogRecord
    @NeedDecrypt
    @UseDataSource(value = "db2")
    @GetMapping(value = "/get/account1")
    public R<List<TbAccount>> getAccount1(){
        List<TbAccount> tbAccounts = accountService.getAccount1();
        return R.ok(tbAccounts);
    }

    @LogRecord
    @NeedDecrypt
    @GetMapping(value = "/get/account")
    public R<List<TbAccount>> getAccount(@RequestParam(value = "dbName",required = false) String dbName){
        if(StringUtils.isNotBlank(dbName)){
            DataSourceKey.use(dbName);
        }
        List<TbAccount> tbAccounts = accountService.getMapper().selectAll();
        DataSourceKey.clear();
        return R.ok(tbAccounts);
    }

    @NeedEncrypt
    @PostMapping(value = "/add/account")
    @UseDataSource(value = "db1")
    @Transactional(rollbackFor = Exception.class)
    public R<TbAccount> addAccount(@RequestBody TbAccount account){
        accountService.saveOrUpdate(account);
        int a = 8;
        int b = a/0;
        return R.ok(account);
    }

    @NeedEncrypt
    @PostMapping(value = "/add/account1")
    @UseDataSource(value = "db2")
    @Transactional(rollbackFor = Exception.class)
    public R<TbAccount> addAccount1(@RequestBody TbAccount account){
        accountService.saveOrUpdate(account);
        int a = 8;
        int b = a/0;
        return R.ok(account);
    }
}
